/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.math.RoundingMode;
import java.text.DecimalFormat;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.SignConstants;

/**
 * 数学相关工具类
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Maths")
public class Maths implements SignConstants
{
    /**
     * 求2的n幂次方的值，直接得到长整型，比Math.pow()得到double要简单
     * 
     * @param n         N次方，N>=0
     * @return          2的N次方的值，长整型
     */
    public static long pow2(int n)
    {
        Asserts.as(n >= 0?null:"幂次方值必须大于等于0");
        return 2L << (n-1);
    }
    
    /**
     * 求10的n幂次方的值，直接得到长整型
     * 
     * @param n     N次方，N>=0
     * @return      10的N次方的值，长整型
     */
    public static long pow10(int n)
    {
        Asserts.as(n >= 0?null:"幂次方值必须大于等于0");
        long val = 1;
        for (int i=0;i<n;i++)
            val *= 10;
        return val;
    }
    
    /**
     * 提供被除数，除数和小数位数，得到结果，不足小数位的不补0，，超过小数位的默认采用floor去尾法
     * 
     * @param dividend  被除数，字符串格式
     * @param divisor   除数
     * @param radixLen  小数位数
     * @return          String 结果
     */
    public static String division(String dividend, long divisor, int radixLen)
    {
        Asserts.asInteger(dividend);
        
        long dividendLong = Long.parseLong(dividend);
        return division(dividendLong, divisor, radixLen, false);
    }
    
    /**
     * 提供被除数，除数和小数位数，得到结果，不足小数位的补0，超过小数位的默认采用floor去尾法
     * 
     * @param dividend  被除数，字符串格式
     * @param divisor   除数
     * @param radixLen  小数位数
     * @return          String 结果
     */
    public static String divisionMustRadix(String dividend, long divisor, int radixLen)
    {
        Asserts.asInteger(dividend);
        
        long dividendLong = Long.parseLong(dividend);
        return division(dividendLong, divisor, radixLen, true);
    }
    
    /**
     * 提供被除数，除数和小数位数，得到结果，默认不保留完整小数位，超过小数位的默认采用floor去尾法
     * 
     * @param dividend  被除数，数值格式
     * @param divisor   除数
     * @param radixLen  小数位数
     * @return          String 结果
     */
    public static String division(long dividend, long divisor, int radixLen)
    {
        return division(dividend, divisor, radixLen, false);
    }
    
    /**
     * 提供被除数，除数和小数位数，得到结果，不足小数位的补0，超过小数位的默认采用floor去尾法
     * 
     * @param dividend  被除数，数值格式
     * @param divisor   除数
     * @param radixLen  小数位数
     * @return          String 结果
     */
    public static String divisionMustRadix(long dividend, long divisor, int radixLen)
    {
        return division(dividend, divisor, radixLen, true);
    }
    
    /**
     * 提供被除数，除数和小数位数，得到结果，注意：默认采用floor去尾法
     * 
     * @param dividend  被除数，数值格式
     * @param divisor   除数
     * @param radixLen  小数位数
     * @return          String 结果
     */
    public static String division(long dividend, long divisor, int radixLen, boolean mustRadix)
    {
        if (radixLen <= 0)
            return String.valueOf(dividend / divisor);
        
        double value = (double)dividend / divisor;
        StringBuilder radix = new StringBuilder("0.");
        for (int i=0;i<radixLen;i++)
        {//得到0.00这种格式
            radix.append(mustRadix?"0":"#");
        }
        
        DecimalFormat formater = new DecimalFormat(radix.toString());
        formater.setRoundingMode(RoundingMode.FLOOR);
        return formater.format(value);
    }
    
    /**
     * 对整数增加千分号后，转为字符串，如32323211转为32,323,211
     * 
     * @param value     整数，如：32323211
     * @return          加千分号的字符串，如：32,323,211
     */
    public static String permil(long value)
    {
        StringBuilder strb = new StringBuilder();
        while (value >= 1000)
        {
            long remainder = value % 1000;
            value = value / 1000;
            
            strb.insert(0, Strings.prefixZero(remainder, 3));
            strb.insert(0, ",");
        }
        
        strb.insert(0, value);
        return strb.toString();
    }
    
    /**
     * 对文件大小进行K/M/G处理，保留指定小数位数
     * 
     * @param value     大小值
     * @param radixLen  小数位数
     * @return          转为K/M/G的小数值
     */
    public static String size(long value, int radixLen)
    {
        if (value < KiB)
            return value + "B";
        else if (value < MiB)
            return division(value, KiB, radixLen) + "K";
        else if (value < GiB)
            return division(value, MiB, radixLen) + "M";
        else
            return division(value, GiB, radixLen) + "G";
    }
}
